package com.xgk.boot.framework.common.util.file;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;

import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

public class ElmFileUtils {

    private static final Map<String, String> MIME_TO_EXTENSION = new HashMap<>();
    private static final Map<String, String> EXTENSION_TO_TYPE = new HashMap<>();



//    public static void main(String[] args) {
//        String url = "https://files.mothership.com/api/file/external/v1/508531e3-f90f-42cb-9d27-7ff835c5e152-3f-a89c9e/redirect";
//        FileTypeInfo fileTypeInfo = detectFile(url);
//        System.out.println(fileTypeInfo);
//        String orderCode="S0922025081300123123";
//        String type="proofOfDelivery";
////        String fileNameNoExtend = orderCode+"_"+type;
////        String fileName = fileNameNoExtend+"."+fileTypeInfo.getExtension();
//        String path = "C:\\Users\\byf78\\Desktop\\日志分析\\wb\\test";
//        String savePath = buildPath(orderCode, type, fileTypeInfo.getExtension(), path);
//        long downloadLength = saveFileFromUrl(url, savePath);
//        System.out.println(String.format("下载异常,download:{%s}",downloadLength));
////        if(fileTypeInfo.getFileLength() == downloadLength){
////            System.out.println("下载成功");
////        }else {
////            System.out.println(String.format("下载异常,src：{%s},download:{%s}",fileTypeInfo.fileLength,downloadLength));
////        }
//    }

    /**
     * 构建文件路径（跨平台兼容）
     * @param orderCode 订单号
     * @param type 文件类型标识
     * @param extension 文件类型信息
     * @param baseDir 基础目录
     * @return 完整文件路径
     */
    public static String buildPath(String orderCode, String type,
                                   String extension, String baseDir) {
        // 1. 构建文件名组件
        String fileName = String.join("_", orderCode, type)
                + "." + extension;
        if(StrUtil.isBlank(baseDir)){
            return fileName;
        }
        // 2. 使用Hutool规范化路径
        return FileUtil.normalize(
                Paths.get(baseDir, fileName).toString()
        );
    }




    /**
     * 构建文件路径（带日期子目录）
     */
    public static String buildPathWithDate(String orderCode, String type,
                                           FileTypeInfo fileTypeInfo, String baseDir) {
        // 添加日期目录（格式：yyyyMMdd）
        String dateDir = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);

        return FileUtil.normalize(
                Paths.get(baseDir, dateDir,
                                String.join("_", orderCode, type)
                                        + "." + fileTypeInfo.getExtension())
                        .toString()
        );
    }



    public static long saveFileFromUrl(String fileURL,String savePath){
        return HttpUtil.downloadFile(fileURL, FileUtil.file(savePath));
    }

    /**
     * 构建文件路径（跨平台兼容）
     *  @param fileURL 文件url地址
     * @param orderCode 订单号
     * @param type 文件类型标识
     * @return 完整文件相关信息
     */
    public static FileTypeInfo detectFile(String fileURL,String orderCode,String type) {
        FileTypeInfo fileTypeInfo = detectFile(fileURL);
        // 1. 构建文件名组件

        String fileName = type
                + "." + fileTypeInfo.getExtension();
        if(StrUtil.isNotBlank(orderCode)){
            fileName = orderCode + StrUtil.SLASH + fileName;
        }
        fileTypeInfo.setFileName(fileName);
        return fileTypeInfo;
    }


    /**
     * 综合判断文件类型
     */
    public static FileTypeInfo detectFile(String fileURL) {
        FileTypeInfo info = new FileTypeInfo();
        info.setUrl(fileURL);

        try {
            // 1. 首先尝试HEAD请求获取Content-Type
            String contentType = getContentTypeByHead(fileURL);
            if (StrUtil.isNotBlank(contentType)) {
                info.setContentType(contentType);
                info.setExtension(getExtensionFromContentType(contentType));
                info.setConfidence(80); // 高置信度
                return info;
            }

            // 2. 如果HEAD失败，尝试从URL路径获取扩展名
            String urlExtension = getExtensionFromUrl(fileURL);
            if (!"unknown".equals(urlExtension)) {
                info.setExtension(urlExtension);
                info.setConfidence(60); // 中等置信度
                return info;
            }

            // 3. 最后尝试GET请求获取Content-Type
            contentType = getContentTypeByGet(fileURL);
            if (StrUtil.isNotBlank(contentType)) {
                info.setContentType(contentType);
                info.setExtension(getExtensionFromContentType(contentType));
                info.setConfidence(70);
                return info;
            }
            //设置默认类型
            info.setExtension("pdf");
            info.setConfidence(0);
//            long fileLength = getFileLength(fileURL);
//            info.setFileLength(fileLength);

        } catch (Exception e) {
            info.setError(e.getMessage());
        }

        return info;
    }

    /**
     * 通过HEAD请求获取Content-Type
     */
    private static String getContentTypeByHead(String fileURL) {
        try {
            HttpResponse response = HttpRequest.head(fileURL)
                    .timeout(5000)
                    .execute();

            if (response.isOk()) {
                return response.header("Content-Type");
            }
        } catch (Exception e) {
            // 静默处理，尝试其他方法
        }
        return null;
    }


    public static String getContentTypeByFileName(String fileName) {
        if (fileName == null || fileName.isEmpty()) {
            return "application/octet-stream";
        }

        String extension = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();

        switch (extension) {
            // 文档类型
            case "pdf": return "application/pdf";
            case "doc": return "application/msword";
            case "docx": return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
            case "xls": return "application/vnd.ms-excel";
            case "xlsx": return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            case "ppt": return "application/vnd.ms-powerpoint";
            case "pptx": return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
            case "txt": return "text/plain";
            case "rtf": return "application/rtf";
            case "csv": return "text/csv";

            // 图片类型
            case "jpg": case "jpeg": return "image/jpeg";
            case "png": return "image/png";
            case "gif": return "image/gif";
            case "bmp": return "image/bmp";
            case "webp": return "image/webp";
            case "svg": return "image/svg+xml";
            case "ico": return "image/x-icon";
            case "tiff": case "tif": return "image/tiff";

            // 音频类型
            case "mp3": return "audio/mpeg";
            case "wav": return "audio/wav";
            case "ogg": return "audio/ogg";
            case "m4a": return "audio/mp4";
            case "flac": return "audio/flac";
            case "aac": return "audio/aac";

            // 视频类型
            case "mp4": return "video/mp4";
            case "avi": return "video/x-msvideo";
            case "mov": return "video/quicktime";
            case "wmv": return "video/x-ms-wmv";
            case "flv": return "video/x-flv";
            case "webm": return "video/webm";
            case "mpeg": case "mpg": return "video/mpeg";

            // 压缩文件
            case "zip": return "application/zip";
            case "rar": return "application/vnd.rar";
            case "7z": return "application/x-7z-compressed";
            case "tar": return "application/x-tar";
            case "gz": return "application/gzip";

            // 代码文件
            case "html": case "htm": return "text/html";
            case "css": return "text/css";
            case "js": return "application/javascript";
            case "json": return "application/json";
            case "xml": return "application/xml";
            case "php": return "application/x-httpd-php";
            case "java": return "text/x-java-source";
            case "py": return "text/x-python";
            case "c": return "text/x-c";
            case "cpp": return "text/x-c++";

            // 字体文件
            case "ttf": return "font/ttf";
            case "otf": return "font/otf";
            case "woff": return "font/woff";
            case "woff2": return "font/woff2";
            case "eot": return "application/vnd.ms-fontobject";

            // 其他常见类型
            case "exe": return "application/x-msdownload";
            case "dmg": return "application/x-apple-diskimage";
            case "apk": return "application/vnd.android.package-archive";
            case "ipa": return "application/x-itunes-ipa";

            default: return "application/octet-stream";
        }
    }

    /**
     * 通过GET请求获取Content-Type
     */
    private static String getContentTypeByGet(String fileURL) {
        try {
            HttpResponse response = HttpRequest.get(fileURL)
                    .timeout(3000) // 短超时，避免下载大文件
                    .execute();

            if (response.isOk()) {
                return response.header("Content-Type");
            }
        } catch (Exception e) {
            // 静默处理
        }
        return null;
    }

    /**
     * 从Content-Type获取扩展名
     */
    private static String getExtensionFromContentType(String contentType) {
        if (StrUtil.isBlank(contentType)) {
            return "unknown";
        }

        String lowerContentType = contentType.toLowerCase();

        // 检查精确匹配
        for (Map.Entry<String, String> entry : MIME_TO_EXTENSION.entrySet()) {
            if (lowerContentType.contains(entry.getKey())) {
                return entry.getValue();
            }
        }

        // 从Content-Type中提取
        if (lowerContentType.contains("/")) {
            String part = lowerContentType.split("/")[1];
            // 去除可能的参数（如charset）
            part = part.split(";")[0].trim();
            if (part.length() <= 5 && !part.contains(" ")) {
                return part;
            }
        }

        return "unknown";
    }

    /**
     * 从URL获取扩展名
     */
    private static String getExtensionFromUrl(String url) {
        // 去除查询参数和片段
        String path = url.split("[?#]")[0];

        // 获取最后一个点之后的部分
        int lastDotIndex = path.lastIndexOf('.');
        if (lastDotIndex != -1 && lastDotIndex < path.length() - 1) {
            String extension = path.substring(lastDotIndex + 1).toLowerCase();

            // 验证扩展名是否常见
            if (isValidExtension(extension)) {
                return extension;
            }
        }

        return "unknown";
    }

    /**
     * 验证扩展名是否有效
     */
    private static boolean isValidExtension(String extension) {
        // 常见的文件扩展名
        String[] validExtensions = {
                "jpg", "jpeg", "png", "gif", "webp", "svg",
                "pdf", "zip", "rar", "7z", "tar", "gz",
                "doc", "docx", "xls", "xlsx", "ppt", "pptx",
                "txt", "html", "htm", "css", "js", "json",
                "mp3", "wav", "mp4", "mov", "avi", "mkv"
        };

        for (String validExt : validExtensions) {
            if (validExt.equals(extension)) {
                return true;
            }
        }

        // 检查扩展名长度和格式
        return extension.length() <= 5 &&
                Pattern.matches("^[a-z0-9]+$", extension);
    }

    /**
     * 获取文件大类（图片、文档、视频等）
     */
    public static String getFileCategory(String extension) {
        return EXTENSION_TO_TYPE.getOrDefault(extension, "other");
    }

    /**
     * 获取文件长度（字节）
     * @param fileURL 文件URL
     * @return 文件长度（字节），-1表示获取失败
     */
    public static long getFileLength(String fileURL) {
        // 1. 优先尝试HEAD请求
        Long length = tryHeadRequest(fileURL);
        if (length != null) return length;

        // 2. 尝试Range请求
        length = tryRangeRequest(fileURL);
        if (length != null) return length;

        // 3. 最后尝试GET请求（不下载内容）
        return tryGetRequest(fileURL);
    }

    private static Long tryHeadRequest(String fileURL) {
        try {
            HttpResponse response = HttpRequest.head(fileURL)
                    .timeout(5000)
                    .execute();

            if (response.isOk()) {
                return parseHeader(response.header("Content-Length"));
            }
        } catch (Exception ignore) {}
        return null;
    }

    private static Long tryRangeRequest(String fileURL) {
        try {
            HttpResponse response = HttpRequest.get(fileURL)
                    .header("Range", "bytes=0-0")
                    .timeout(8000)
                    .execute();

            if (response.getStatus() == 206) {
                String contentRange = response.header("Content-Range");
                if (contentRange != null && contentRange.contains("/")) {
                    return parseHeader(contentRange.split("/")[1]);
                }
            }
            return parseHeader(response.header("Content-Length"));
        } catch (Exception ignore) {}
        return null;
    }

    private static long tryGetRequest(String fileURL) {
        try {
            HttpResponse response = HttpRequest.get(fileURL)
                    .timeout(3000)
                    .execute();

            if (response.isOk()) {
                Long length = parseHeader(response.header("Content-Length"));
                return length != null ? length : response.bodyBytes().length;
            }
        } catch (Exception ignore) {}
        return -1;
    }

    private static Long parseHeader(String headerValue) {
        if (StrUtil.isBlank(headerValue)) return null;
        try {
            return Long.parseLong(headerValue.trim());
        } catch (NumberFormatException e) {
            return null;
        }
    }

    /**
     * 文件类型信息类
     */
    public static class FileTypeInfo {
        private String url;
        private String contentType;
        private String extension;
        private String category;
        private int confidence;
        private String error;
        private long fileLength=-1;


        private String fileName;


        public String getFileName() {
            return fileName;
        }

        public void setFileName(String fileName) {
            this.fileName = fileName;
        }

        public FileTypeInfo() {
            this.confidence = 0;
        }

        // Getter和Setter方法
        public String getUrl() { return url; }
        public void setUrl(String url) { this.url = url; }

        public String getContentType() { return contentType; }
        public void setContentType(String contentType) {
            this.contentType = contentType;
            if (extension == null) {
                this.extension = getExtensionFromContentType(contentType);
            }
            if (category == null) {
                this.category = getFileCategory(this.extension);
            }
        }

        public long getFileLength() { return fileLength; }
        public void setFileLength(long fileLength) { this.fileLength = fileLength; }

        public String getExtension() { return extension; }
        public void setExtension(String extension) {
            this.extension = extension;
            if (category == null) {
                this.category = getFileCategory(extension);
            }
        }

        public String getCategory() { return category; }
        public void setCategory(String category) { this.category = category; }

        public int getConfidence() { return confidence; }
        public void setConfidence(int confidence) { this.confidence = confidence; }

        public String getError() { return error; }
        public void setError(String error) { this.error = error; }

        @Override
        public String toString() {
            return String.format("FileTypeInfo{extension=%s, category=%s, confidence=%d%%, contentType=%s,fileLength=%s}",
                    extension, category, confidence, contentType,fileLength);
        }
    }


    static {
        // MIME类型到扩展名的映射
        MIME_TO_EXTENSION.put("image/jpeg", "jpg");
        MIME_TO_EXTENSION.put("image/jpg", "jpg");
        MIME_TO_EXTENSION.put("image/png", "png");
        MIME_TO_EXTENSION.put("image/gif", "gif");
        MIME_TO_EXTENSION.put("image/webp", "webp");
        MIME_TO_EXTENSION.put("image/svg+xml", "svg");
        MIME_TO_EXTENSION.put("application/pdf", "pdf");
        MIME_TO_EXTENSION.put("application/zip", "zip");
        MIME_TO_EXTENSION.put("application/x-rar-compressed", "rar");
        MIME_TO_EXTENSION.put("application/x-zip-compressed", "zip");
        MIME_TO_EXTENSION.put("application/msword", "doc");
        MIME_TO_EXTENSION.put("application/vnd.openxmlformats-officedocument.wordprocessingml.document", "docx");
        MIME_TO_EXTENSION.put("application/vnd.ms-excel", "xls");
        MIME_TO_EXTENSION.put("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "xlsx");
        MIME_TO_EXTENSION.put("application/vnd.ms-powerpoint", "ppt");
        MIME_TO_EXTENSION.put("application/vnd.openxmlformats-officedocument.presentationml.presentation", "pptx");
        MIME_TO_EXTENSION.put("text/plain", "txt");
        MIME_TO_EXTENSION.put("text/html", "html");
        MIME_TO_EXTENSION.put("text/css", "css");
        MIME_TO_EXTENSION.put("text/javascript", "js");
        MIME_TO_EXTENSION.put("application/javascript", "js");
        MIME_TO_EXTENSION.put("application/json", "json");
        MIME_TO_EXTENSION.put("audio/mpeg", "mp3");
        MIME_TO_EXTENSION.put("audio/wav", "wav");
        MIME_TO_EXTENSION.put("video/mp4", "mp4");
        MIME_TO_EXTENSION.put("video/quicktime", "mov");
        MIME_TO_EXTENSION.put("video/x-msvideo", "avi");

        // 扩展名到文件类型的映射
        EXTENSION_TO_TYPE.put("jpg", "image");
        EXTENSION_TO_TYPE.put("jpeg", "image");
        EXTENSION_TO_TYPE.put("png", "image");
        EXTENSION_TO_TYPE.put("gif", "image");
        EXTENSION_TO_TYPE.put("webp", "image");
        EXTENSION_TO_TYPE.put("svg", "image");
        EXTENSION_TO_TYPE.put("pdf", "document");
        EXTENSION_TO_TYPE.put("zip", "archive");
        EXTENSION_TO_TYPE.put("rar", "archive");
        EXTENSION_TO_TYPE.put("7z", "archive");
        EXTENSION_TO_TYPE.put("doc", "document");
        EXTENSION_TO_TYPE.put("docx", "document");
        EXTENSION_TO_TYPE.put("xls", "spreadsheet");
        EXTENSION_TO_TYPE.put("xlsx", "spreadsheet");
        EXTENSION_TO_TYPE.put("ppt", "presentation");
        EXTENSION_TO_TYPE.put("pptx", "presentation");
        EXTENSION_TO_TYPE.put("txt", "text");
        EXTENSION_TO_TYPE.put("html", "web");
        EXTENSION_TO_TYPE.put("css", "web");
        EXTENSION_TO_TYPE.put("js", "web");
        EXTENSION_TO_TYPE.put("json", "data");
        EXTENSION_TO_TYPE.put("mp3", "audio");
        EXTENSION_TO_TYPE.put("wav", "audio");
        EXTENSION_TO_TYPE.put("mp4", "video");
        EXTENSION_TO_TYPE.put("mov", "video");
        EXTENSION_TO_TYPE.put("avi", "video");
    }

}
